package com.unionftech.common.recaptcha

import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import com.google.android.recaptcha.RecaptchaAction
import com.google.gson.Gson
import com.unionftech.common.bean.CaptchaType
import com.unionftech.common.bean.ResponseResult
import com.unionftech.common.network.SimpleNetWork
import com.unionftech.common.utils.ActivityCollector
import com.unionftech.common.utils.LogUtils
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.ResponseBody.Companion.toResponseBody
import java.util.concurrent.CountDownLatch


class RecaptchaInterceptor : Interceptor {
    companion object {
        private const val TAG = "RecaptchaInterceptor"

        /**
         * 需要进行滑块验证的接口，需要添加的Header key
         */
        const val KEY_INTERCEPTOR_ACTION = "RecaptchaAction"

        /**
         * 服务器需要的滑块验证token key
         */
        private const val BEHAVIOR_CHECK_TOKEN = "behaviorCheckToken"

        /**
         * 服务器需要的滑块验证 type key
         */
        private const val BEHAVIOR_TYPE = "behaviorType"
    }

    private var mLatch: CountDownLatch? = null
    private var mCurCaptchaType: CaptchaType = CaptchaType.GOOGLE
    private var mCurToken = ""
    private var mJsCallBack: ((captchaResult: Boolean) -> Unit)? = null
    private val mGson by lazy { Gson() }
    private val mMainHandler = Handler(Looper.getMainLooper())
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()
        //判断是否需要拦截
        var action =
            originalRequest.header(KEY_INTERCEPTOR_ACTION) ?: return chain.proceed(originalRequest)
        var newResponse: Response? = null
        var responseBody: ResponseBody?
        var responseBodyString: String? = null
        var responseResult: ResponseResult<*>? = null
        while (!TextUtils.isEmpty(action)
            || responseResult?.code == ResponseResult.NETEASE_VERIFY
            || responseResult?.code == ResponseResult.ALIYUN_VERIFY
        ) {
            //开始进行同步验证
            startAsyncVerify(responseResult, action)
            //用户取消验证，取消此次网络请求，直接构造CancelResponse
            if (TextUtils.equals(RecaptchaUtil.RECAPTCHA_CANCEL, mCurToken)) {
                return buildCancelResponse(originalRequest)
            }
            LogUtils.d(TAG, "mCurCaptchaTyp->${mCurCaptchaType}")
            LogUtils.d(TAG, "mCurToken->${mCurToken}")
            LogUtils.d(TAG, "mJsCallBack->${mJsCallBack}")
            val request = originalRequest.newBuilder()
                .removeHeader(KEY_INTERCEPTOR_ACTION)
                .addHeader(BEHAVIOR_CHECK_TOKEN, mCurToken)
                .addHeader(BEHAVIOR_TYPE, mCurCaptchaType.type.toString())
                .build()
            newResponse = chain.proceed(request)
            responseBody = newResponse.peekBody(Long.MAX_VALUE)
            responseBodyString = responseBody.string()
            //解析服务返回的结果，while循环判断是否需要开启循环
            responseResult = mGson.fromJson(responseBodyString, ResponseResult::class.java)
            //返回结果不是再次调起滑块验证,说明此次验证结束，关闭并释放滑块,结束循环
            if (responseResult.code != ResponseResult.ALIYUN_VERIFY
                && responseResult.code != ResponseResult.NETEASE_VERIFY
            ) {
                mMainHandler.post {
                    mJsCallBack?.invoke(true)
                    mJsCallBack = null
                    RecaptchaUtil.getInstance().destroy()
                }
                break
            }
            //控制结束第一次google验证
            action = ""
            //开启网易滑块或阿里云滑块的判断
            mLatch = null
            mCurToken = ""
        }

        // 重新构建一个 Response 供后续逻辑使用
        return newResponse!!.newBuilder()
            .body(responseBodyString!!.toResponseBody(newResponse.body?.contentType()))
            .build()
    }

    private fun startAsyncVerify(
        responseResult: ResponseResult<*>?,
        action: String
    ) {
        //首次进行google评分验证
        if (responseResult == null) {
            verify(CaptchaType.GOOGLE, RecaptchaAction.custom(action))
        }
        //接收到服务器的返回结果之后进行网易滑块验证或者阿里云滑块验证
        if (mLatch == null) {
            if (responseResult?.code == ResponseResult.NETEASE_VERIFY) {
                verify(CaptchaType.NETEASE)
            } else if (responseResult?.code == ResponseResult.ALIYUN_VERIFY) {
                verify(CaptchaType.ALIYUN)
            }
        }
        //等待异步验证结果返回
        mLatch?.await()
    }

    private fun buildCancelResponse(originalRequest: Request): Response {
        val cancelBodyString = mGson.toJson(ResponseResult.buildCancel(null))
        return Response.Builder()
            .code(200) // HTTP 状态码
            .message("OK") // 状态消息
            .request(originalRequest) // 关联的请求
            .protocol(Protocol.HTTP_1_1) // 协议版本
            .body(cancelBodyString.toResponseBody(SimpleNetWork.JSON)) // 响应体
            .addHeader("Content-Type", "application/json") // 添加响应头
            .build()
    }

    private fun verify(type: CaptchaType, action: RecaptchaAction? = null) {
        ActivityCollector.getCurrentActivity()?.also { activity ->
            //开启同步等待计数
            mLatch = CountDownLatch(1)
            mMainHandler.post {
                when (type) {
                    CaptchaType.NETEASE -> RecaptchaUtil.getInstance()
                        .verifyWithNetease(activity, ::verifyCallBack)

                    CaptchaType.ALIYUN -> {
                        if (mJsCallBack != null) {
                            mMainHandler.post {
                                mJsCallBack?.invoke(false)
                            }
                        } else {
                            RecaptchaUtil.getInstance().verifyWithAliyun(activity, ::verifyCallBack)
                        }
                    }

                    CaptchaType.GOOGLE -> action?.let {
                        RecaptchaUtil.getInstance().verifyWithGoogle(activity, it, ::verifyCallBack)
                    }
                }
            }
        }
    }

    private fun verifyCallBack(
        captchaType: CaptchaType,
        token: String?,
        jsCallBack: ((captchaResult: Boolean) -> Unit)?
    ) {
        mCurCaptchaType = captchaType
        mCurToken = token ?: ""
        mJsCallBack = jsCallBack
        if (!TextUtils.isEmpty(token)) {
            //验证结果返回，同步计数等待结束
            mLatch?.countDown()
        }
    }
}